package org.changchen.fgt.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.changchen.fgt.dto.DoubanHotDto;
import org.changchen.fgt.service.DoubanHotService;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import cn.hutool.core.date.DateUtil;

@Service
public class DoubanHotServiceImpl implements DoubanHotService{
	
	
	private static final String DOUBAN_URL = "https://movie.douban.com/j/search_subjects?type=%s&tag=%s&page_limit=%d&page_start=%d";
	
	
	private static final String TYPE_TV = "tv";
	
	private static final String TYPE_MOVIE = "movie";
	
	private static final String IMG_DIR = "img/";

	
	private static Map<String, List<DoubanHotDto>> HOT_MAP = new HashMap<>();
	
	
	
	@Override
	public List<DoubanHotDto> getDoubanHot(String tag, int page, int size){
		
		Map<Long, List<DoubanHotDto>> allMap = new HashMap<>();
		allMap.put(0L, this.getDoubanHotTv(tag, page, size));
		allMap.put(1L, this.getDoubanHotMovie(tag, page, size));
		
		List<DoubanHotDto> allList = new ArrayList<>();
		
		// 电影/剧集随机排序
		Random random = new Random();
		long key = Math.round(random.nextDouble());
		
		allList.addAll(allMap.get(key));
		allList.addAll(allMap.get(1 - key));
		
		// allList.sort((video1, video2) -> {return video2.getRate().compareTo(video1.getRate());});
		
		return allList;
	}
	
	
	
	@Override
	public List<DoubanHotDto> getDoubanHotTv(String tag, int page, int size){
		String key = this.getCacheKey(TYPE_TV, tag, page, size);
		List<DoubanHotDto> hotList = HOT_MAP.get(key);
		if(hotList == null) {
			hotList = this.getDoubanHot(TYPE_TV, tag, (page-1)*size, size);
			HOT_MAP.put(key, hotList);
		}
		
		return hotList;
	}
	
	
	@Override
	public List<DoubanHotDto> getDoubanHotMovie(String tag, int page, int size){
		String key = this.getCacheKey(TYPE_MOVIE, tag, page, size);
		List<DoubanHotDto> hotList = HOT_MAP.get(key);
		if(hotList == null) {
			hotList = this.getDoubanHot(TYPE_MOVIE, tag, (page-1)*size, size);
			HOT_MAP.put(key, hotList);
		} 		
		return hotList;
	}
	
	
	private List<DoubanHotDto> getDoubanHot(String type, String tag, int start, int size) {
		
		String url = String.format(DOUBAN_URL, type, tag, size, start);
		
        String doubanHot = WebClient.create().get().uri(url).retrieve().bodyToMono(String.class).block();
        if(StringUtils.isBlank(doubanHot)) {
        	return Collections.emptyList();
        }
        
        JSONObject jsonObj = JSONObject.parseObject(doubanHot);
        JSONArray subjects = jsonObj.getJSONArray("subjects");
        
        List<DoubanHotDto> resultList = new ArrayList<>();
        for(int i=0;i<subjects.size();i++) {
        	JSONObject subject = subjects.getJSONObject(i);
        	String name = subject.getString("title");
        	String cover = subject.getString("cover");
        	String rate = subject.getString("rate");
        	DoubanHotDto dto = new DoubanHotDto();
        	dto.setCover(cover);
        	dto.setName(name);
        	dto.setRate(rate);
        	resultList.add(dto);
        }
		
        return resultList;
	}
	
	
	@Override
	public void doubanImage(HttpServletResponse response, String imgUrl) throws FileNotFoundException, IOException {

		// 图片文件名
		String fileName = imgUrl.substring(imgUrl.lastIndexOf("/"));
		
		// 图片缓存目录
		String imgDir = this.getParentDir() + File.separator + IMG_DIR; 
		File imgDirFile = new File(imgDir);
		if(!imgDirFile.exists()) {
			imgDirFile.mkdirs();
		}
		
		// 图片缓存
		File imgFile = new File(imgDir + fileName);
		if(!imgFile.exists()) {
			// 下载图片缓存
			Resource resource = WebClient.create().get().uri(imgUrl).accept(MediaType.APPLICATION_OCTET_STREAM).retrieve().bodyToMono(Resource.class).block();			
			FileOutputStream fos = null;
			try {
			    fos = new FileOutputStream(imgFile);
			    IOUtils.copy(resource.getInputStream(), fos);
			}finally{
			    IOUtils.closeQuietly(fos);
			}
		}
		
		// 图片
		// 响应头
		response.setContentType("image/webp");
		FileInputStream imgInputStream = new FileInputStream(imgFile);
    	IOUtils.copy(imgInputStream, response.getOutputStream());
		
	}
	
	
	/**   
	 * @Title:      getParentDir   
	 * @Description:获取 Jar 所在目录   
	 * @param:      @return      
	 * @return:     String      
	 * @throws   
	 */
	public String getParentDir() {
		// 获取 jar 所在目录
		ApplicationHome home = new ApplicationHome(this.getClass());
		File jarFile = home.getSource();
		return jarFile.getParentFile().toString();
	}
	
	
	/**   
	 * @Title:      getCacheKey   
	 * @Description:缓存Key   
	 * @param:      @param type
	 * @param:      @param tag
	 * @param:      @return      
	 * @return:     String      
	 * @throws   
	 */
	private String getCacheKey(String type, String tag, Integer page, Integer size) {
		
		String datetime = DateUtil.format(new Date(), "yyyyMMddHH");
		
		// 删除过期的缓存
		HOT_MAP.keySet().removeIf(key -> !key.startsWith(datetime));
		
		String currentKey = String.format("%s-%s-%s-%d-%d", datetime, type, tag, page, size);
		
		return currentKey;
	}
	
		
}
